package libvirt;

import model.MacAddress;
import model.exception.MacAddressException;
import org.apache.log4j.Logger;
import org.libvirt.Connect;
import org.libvirt.ConnectAuth;
import org.libvirt.ConnectAuthDefault;
import org.libvirt.Domain;
import org.libvirt.LibvirtException;
import java.util.UUID;

/**
 * @author Dumella De Rosa Gennaro
 *
 */
public class LIBVIRTConnectionHandler{
	
	private static final Logger log = Logger.getLogger(LIBVIRTConnectionHandler.class);
	
	private Connect conn;
	private enum Unit{gigabit, megabit, kilobit};
	private enum Period{second, millisecond, microsecond};

    public LIBVIRTConnectionHandler(Connect conn) {
		this.conn = conn;
	}
    
	/**
	 * Fornisce la descrizione xml del dominio identificato da uuid
	 * 
	 * @param uuid - Identificazione del dominio
	 * @throws LibvirtException 
	 */
    public String getDomainXMLDesc(UUID uuid) throws LibvirtException{
		Domain domain = conn.domainLookupByUUID(uuid);
		return domain.getXMLDesc(0);
    }
    
	/**
	 * Crea una virtual interface con rate massimo stabilito e la collega al backend
	 * 
	 * @param uuid - Identificativo del dominio
	 * @param ...
	 * @throws LibvirtException 
	 */
    public void attachInterface(UUID uuid, String interfaceType, MacAddress macAddress, String sourceBridge,
    		String scriptPath, String targetDev,Unit unit,Period period,int value ) throws LibvirtException{
    	
    	String xmlDesc;
    	if(unit != null && period != null && rateIsValid(unit, period, value))
    		xmlDesc = getXmlDescription(interfaceType, macAddress, sourceBridge, scriptPath, targetDev, unit, period, value);
    	else
    		xmlDesc = getXmlDescription(interfaceType, macAddress, sourceBridge, scriptPath, targetDev, null, null, 0);
    	
    	Domain domain = conn.domainLookupByUUID(uuid);		
    	domain.attachDevice(xmlDesc);
    }
    
	/**
	 * Distrugge un virtual interface collegata al backend
	 * 
	 * @param uuid - Identificativo del dominio
	 * @param MACAddress - Indirizzo MAC del dispositivo
	 * @param bridge - Bridge a cui è connesso il virtual device
	 * @throws LibvirtException 
	 */
    public void detachInterface(UUID uuid, String interfaceType, MacAddress macAddress, String sourceBridge,
    								String scriptPath, String targetDev) throws LibvirtException{
    	Domain domain = conn.domainLookupByUUID(uuid);
    	String xmlDesc = getXmlDescription(interfaceType, macAddress, sourceBridge, scriptPath, targetDev, null,null,0);
		domain.detachDevice(xmlDesc);
    }   
    
	/**
	 * Chiude la connessione libvirt legata a questo gestore
	 * @throws LibvirtException 
	 */
	public void close() throws LibvirtException {
		if (this.conn != null)
			this.conn.close();
		log.info("Disconnected!");
	}
	
	public String getXmlDescription(String interfaceType, MacAddress macAddress, String sourceBridge,
    									String scriptPath, String targetDev,Unit unit,Period period,
    									int value){
		
		String xmlDesc ="<interface type='"  +interfaceType+			"'>\n" +
						"	<mac address='"  +macAddress.toString()+	"'/>\n" +
						"	<source bridge='"+sourceBridge+				"'/>\n" +
						"	<script path='"  +scriptPath+				"'/>\n" +
						"	<target dev='"   +targetDev+				"'/>\n";

		if ( unit != null && period != null && rateIsValid(unit,period,value) )
		  {	
			xmlDesc += 	"	<networkresource> \n" +
					    "		<capped-bandwidth unit='"+unit+"' period='"+period+"' value='"+value+"'/>\n" +
					    "	</networkresource> \n";
		  }
		xmlDesc += "</interface>";
		
		return xmlDesc;
	}

	private boolean rateIsValid(Unit unit,Period period,int value){
			return true;
	}
	
	public static LIBVIRTConnectionHandler createLIBVIRTConnectionHandler(
				String driver, String transport,String username,String hostname,String port,String path,
				String extraparameters, ConnectAuth connectAuth, int flags)	throws LibvirtException {

			
			String remoteURI = driver;
			if(port == null && path == null && extraparameters == null)	
				remoteURI = remoteURI+"+"+transport+"://"+username+"@"+hostname;
			else
				remoteURI = remoteURI+"+"+transport+"://"+username+"@"+hostname+":"+port+"/"+path;
			
			log.info("Try to connect to " + remoteURI + "...");
        	
        	Connect conn = new Connect(remoteURI,connectAuth,flags);

        	log.info("... connected to " + remoteURI);
    		
        	return new LIBVIRTConnectionHandler(conn);
	}
	
	
	public static void main(String[] args) throws MacAddressException 
	{	
		try {
			
			LIBVIRTConnectionHandler handler = LIBVIRTConnectionHandler.createLIBVIRTConnectionHandler("xen","ssh","root",
					"192.168.74.16",null,null, null, new ConnectAuthDefault(), 0);
			
			//macchina 4 c4a20056-6522-72b8-534d-67fa315c6ca5
			//macchina 1 2516f6de-3598-a33b-5f2c-3a58fca21490
			UUID uuid = java.util.UUID.fromString("2516f6de-3598-a33b-5f2c-3a58fca21490");
			
			handler.detachInterface(uuid,"bridge",new MacAddress("00:16:3e:01:02:01"),"eth1","vif-bridge","id01eth1");
			
			handler.attachInterface(uuid,"bridge",new MacAddress("00:16:3e:01:02:01"),"eth1","vif-bridge",
											"id01eth1",null,null,8);
			
			System.out.println(handler.getXmlDescription("bridge", new MacAddress("00:16:3E:AA:AA:AA"), "vif-bridge", "/pippo/pippo", "id01eth0", Unit.kilobit, Period.second, 12));
			System.out.println(handler.getXmlDescription("bridge", new MacAddress("00:16:3E:AA:AA:AA"), "vif-bridge", "/pippo/pippo", "id01eth1", null, Period.second, 12));
			
			
			handler.close();
				
		} catch (LibvirtException e) {
			e.printStackTrace();
		}	
	}

}
